package com.sixj.keycloakssointegration.demo;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.*;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;

public class KeycloakImpersonationExample {

    // Keycloak 配置
    static final String KEYCLOAK_BASE_URL = "https://192.168.173.171";
    static final String REALM = "runlion";
    static final String ADMIN_USERNAME = "admin";
    static final String ADMIN_PASSWORD = "admin";
    static final String CLIENT_ID = "admin-cli";
    static final String USER_ID_TO_IMPERSONATE = "f:9eca388c-3935-4737-b33d-3c4c54836e26:1202179443109826562";

    public static void main(String[] args) throws Exception {


        // 1. 获取管理员 Token
        String token = getAdminToken();

        // 2. 发起 Impersonation
        String impersonateUrl = impersonateUser(token, USER_ID_TO_IMPERSONATE);
        System.out.println("Impersonation login URL: " + impersonateUrl);
        // 3. 浏览器重定向 impersonateUrl 即可自动以目标用户身份登录 Keycloak
    }

    // 获取 Keycloak 管理员 Access Token
    private static String getAdminToken() throws Exception {
        SSLContext sslContext = SSLContexts.custom()
                .loadTrustMaterial((chain, authType) -> true) // 信任所有
                .build();

        CloseableHttpClient client = HttpClients.custom()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
        HttpPost post = new HttpPost(KEYCLOAK_BASE_URL + "/realms/master/protocol/openid-connect/token");

        String body = "client_id=" + CLIENT_ID +
                "&username=" + ADMIN_USERNAME +
                "&password=" + ADMIN_PASSWORD +
                "&grant_type=password";
        post.setHeader("Content-Type", "application/x-www-form-urlencoded");
        post.setEntity(new StringEntity(body));

        String response = EntityUtils.toString(client.execute(post).getEntity());
        JsonNode node = new ObjectMapper().readTree(response);
        return node.get("access_token").asText();
    }

    // 调用 Impersonation API
    private static String impersonateUser(String token, String userId) throws Exception {
        SSLContext sslContext = SSLContexts.custom()
                .loadTrustMaterial((chain, authType) -> true) // 信任所有
                .build();

        CloseableHttpClient client = HttpClients.custom()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
        HttpPost post = new HttpPost(KEYCLOAK_BASE_URL + "/admin/realms/" + REALM + "/users/" + userId + "/impersonation");
        post.setHeader("Authorization", "Bearer " + token);

        CloseableHttpResponse response = client.execute(post);
        int status = response.getStatusLine().getStatusCode();
        if (status != 200 && status != 201) {
            throw new RuntimeException("Impersonation failed, status: " + status);
        }
        // 返回 impersonation 跳转链接，通常在 Set-Cookie/Location 响应头
        // 最安全的方式是解析响应体里的跳转URL
        String responseBody = EntityUtils.toString(response.getEntity());
        JsonNode node = new ObjectMapper().readTree(responseBody);
        String impersonationUrl = node.get("redirect").asText();
        return impersonationUrl;
    }
}
